/**
 * 防抖工具函数
 * 用于处理拖拽完成后的接口调用，支持特殊的防抖逻辑
 */

interface DebounceOptions {
  delay?: number; // 延迟时间，默认3000ms
  cancelThreshold?: number; // 取消阈值，默认1000ms
}

export interface DebounceInstance {
  execute: (...args: any[]) => void;
  cancel: () => void;
  clear: () => void;
}

/**
 * 创建一个防抖函数实例
 * @param fn 要执行的函数
 * @param options 配置选项
 * @returns 防抖函数实例
 */
export function createDebounce<T extends (...args: any[]) => any>(
  fn: T,
  options: DebounceOptions = {}
): DebounceInstance {
  const { delay = 3000, cancelThreshold = 1000 } = options;
  
  let timeoutId: NodeJS.Timeout | null = null;
  let lastCallTime = 0;

  const execute = (...args: Parameters<T>) => {
    const currentTime = Date.now();
    
    // 如果距离上次调用不到1秒，取消之前的调用
    if (currentTime - lastCallTime < cancelThreshold && timeoutId) {
      clearTimeout(timeoutId);
      timeoutId = null;
    }
    
    lastCallTime = currentTime;
    
    // 清除之前的定时器
    if (timeoutId) {
      clearTimeout(timeoutId);
    }
    
    // 设置新的定时器
    timeoutId = setTimeout(() => {
      fn(...args);
      timeoutId = null;
    }, delay);
    
  };

  const cancel = () => {
    if (timeoutId) {
      clearTimeout(timeoutId);
      timeoutId = null;
    }
  };

  const clear = () => {
    cancel();
    lastCallTime = 0;
  };

  return {
    execute,
    cancel,
    clear
  };
}

/**
 * 简单的防抖函数（传统防抖）
 * @param fn 要执行的函数
 * @param delay 延迟时间
 * @returns 防抖后的函数
 */
export function debounce<T extends (...args: any[]) => any>(
  fn: T,
  delay: number = 300
): (...args: Parameters<T>) => void {
  let timeoutId: NodeJS.Timeout | null = null;

  return (...args: Parameters<T>) => {
    if (timeoutId) {
      clearTimeout(timeoutId);
    }
    
    timeoutId = setTimeout(() => {
      fn(...args);
    }, delay);
  };
}

/**
 * 节流函数
 * @param fn 要执行的函数
 * @param delay 节流间隔
 * @returns 节流后的函数
 */
export function throttle<T extends (...args: any[]) => any>(
  fn: T,
  delay: number = 300
): (...args: Parameters<T>) => void {
  let lastCallTime = 0;

  return (...args: Parameters<T>) => {
    const currentTime = Date.now();
    
    if (currentTime - lastCallTime >= delay) {
      lastCallTime = currentTime;
      fn(...args);
    }
  };
}